Skip to content

url: speed up WHATWG URL parsing - #65361

Open
anonrig wants to merge 2 commits into
nodejs:mainfrom
anonrig:cursor/url-parse-performance-603e
Open

url: speed up WHATWG URL parsing#65361
anonrig wants to merge 2 commits into
nodejs:mainfrom
anonrig:cursor/url-parse-performance-603e

Conversation

@anonrig

@anonrig anonrig commented Aug 18, 2026

Copy link
Copy Markdown
Member

Speeds up new URL() / URL.parse() on the common path: already-serialized ASCII hrefs.

The binding currently always:

  1. Copies the V8 string into a UTF-8 buffer (Utf8Value)
  2. Parses with Ada
  3. Allocates a new V8 string from href, even when it is byte-identical to the input

Typical URLs (https://example.com/path, the whatwg-url-parse benchmark corpus) are one-byte ASCII and already in serialized form. This change:

  • Parses one-byte ASCII inputs in place via v8::String::ValueView (no UTF-8 copy)
  • Returns the original V8 string when href == input (no second string allocation)
  • Avoids copying the base URL into a temporary std::string just to parse it
  • Applies the same in-place parse to update() (setters re-parse an already-serialized href)
  • Delays URLContext allocation until parse finishes, and initializes it in one shot from urlComponents
  • Skips `${input}` when the value is already a string

Non-ASCII inputs still go through Utf8Value. Those results are never reused as the original string, because UTF-8 conversion may replace unpaired surrogates.

Benchmark

Same machine, Release build, benchmark/url/whatwg-url-parse.js e=12. Repeated runs:

Config Before (ops/s) After (ops/s) Change
short / no base 7.82M 9.29M +19%
long / no base 2.50M 2.75M +10%
short / with base 2.94M 3.39M +15%

dot (needs path normalization, so a new href string) is unchanged.

Review follow-up

  • reuse_input defaults to nullptr. Base-URL parse and update() omit it so we skip the O(n) href == input compare when the original V8 string will not be reused.

Tests

  • test/parallel/test-whatwg-url-*.js and test-url-*.js: 54 pass, 1 skip
  • WPT url: 5107 pass, 0 unexpected failures
  • New test/parallel/test-whatwg-url-parse-fast-path.js covers already-serialized ASCII hrefs, trailing-slash and dot-segment normalization, base resolution, non-string input, invalid input, unpaired surrogates, IDN, and setters

Assisted-by: Cursor

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/url

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. whatwg-url Issues and PRs related to the WHATWG URL implementation. labels Aug 18, 2026
@anonrig
anonrig requested review from jasnell and mcollina August 18, 2026 01:33
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.08738% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.11%. Comparing base (13fcd6f) to head (7589246).
⚠️ Report is 66 commits behind head on main.

Files with missing lines Patch % Lines
src/node_url.cc 93.18% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65361      +/-   ##
==========================================
- Coverage   91.85%   90.11%   -1.74%     
==========================================
  Files         400      752     +352     
  Lines      178855   252356   +73501     
  Branches    27319    47474   +20155     
==========================================
+ Hits       164283   227413   +63130     
- Misses      14243    16224    +1981     
- Partials      329     8719    +8390     
Files with missing lines Coverage Δ
lib/internal/url.js 93.28% <100.00%> (+13.12%) ⬆️
src/node_url.cc 78.94% <93.18%> (ø)

... and 490 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jasnell jasnell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI agents are not permitted to Signed-off-by

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch from b9884e1 to a66b5bc Compare August 18, 2026 11:39
@anonrig

anonrig commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

Removed the Signed-off-by trailer from the commit(s). An AI agent cannot attest the DCO.

@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch from a66b5bc to 39c4db7 Compare August 18, 2026 12:49
Parse one-byte ASCII inputs in place instead of copying them into a
UTF-8 buffer, and reuse the original V8 string when the serialized
href is unchanged. Delay URLContext allocation until parse finishes
and skip ToString when the input is already a string.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch 2 times, most recently from fa5ca3f to ed31ad0 Compare August 18, 2026 18:09

@gurgunday gurgunday left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid always comparing the strings here?

Base parsing and setters discard reuse_input, so here we can avoid an O(n) comparison no?

Comment thread src/node_url.cc Outdated
Comment thread src/node_url.cc Outdated
Comment thread src/node_url.cc Outdated
Comment thread src/node_url.cc Outdated
Comment thread src/node_url.cc Outdated
@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch from ed31ad0 to 47af16c Compare August 18, 2026 18:43
@jasnell
jasnell dismissed their stale review August 18, 2026 22:53

Resolved

@mertcanaltin mertcanaltin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I think we can seperate PR same improvement for canParse?

@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch 2 times, most recently from faad7a6 to caa85b0 Compare August 20, 2026 18:57
Callers that never reuse the original V8 string (base URL parse and
setters) now omit reuse_input so ParseUrlFromV8String does not
compare href against the input.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch from caa85b0 to 7589246 Compare August 20, 2026 18:57

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Aug 21, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 21, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@gurgunday gurgunday left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. whatwg-url Issues and PRs related to the WHATWG URL implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants